home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS11.ADF / C / VidTex.c < prev    next >
C/C++ Source or Header  |  1986-08-05  |  14KB  |  357 lines

  1. /*
  2.  * Vidtex version 1.0
  3.  * by George Musser Jr.
  4.  * CIS 76566,3714
  5.  * 25 May 1986
  6.  *
  7.  * This program displays a medium or high resolution Vidtex picture
  8.  * downloaded from CompuServe.  The program tries to scale the picture
  9.  * to fit the current window size; the smaller the window, the more
  10.  * information the algorithm must discard to squeeze the picture.
  11.  *
  12.  * CLI syntax: VIDTEX <file>
  13.  * Workbench:  Select both picture file and VIDTEX
  14.  *
  15.  */
  16.  
  17. #include <exec/types.h>
  18. #include <intuition/intuition.h>
  19. #include <workbench/startup.h>
  20. #include <stdio.h>
  21.  
  22. /* ===== Vidtex definitions ============================================= */
  23.  
  24. #define  MED_X        128     /* Picture elements in medium resolution */
  25. #define  MED_Y         96
  26. #define  HI_X         256     /* Picture elements in high resolution */
  27. #define  HI_Y         192
  28. #define  ZERO         ' '     /* Vidtex code for 0 pixels */
  29. #define  SEQLEN         3     /* Length of escape sequences */
  30. #define  MED_RES   "\x1BGM"   /* Sequence for medium resolution */
  31. #define  HI_RES    "\x1BGH"   /* Sequence for high resolution */
  32. #define  ESC         0x1B     /* Escape character */
  33.  
  34. /* ===== Window definitions ============================================= */
  35.  
  36. #define  MIN_WIDTH          50      /* Smallest window size */
  37. #define  MIN_HEIGHT         25
  38. #define  MAX_WIDTH         640      /* Largest window size */
  39. #define  MAX_HEIGHT        200
  40. #define  HI_WIDTH       MAX_WIDTH   /* Initial window size */
  41. #define  MED_WIDTH         375      /* 2.5*(MED_X+BorderLeft+BorderRight) */
  42. #define  HI_HEIGHT     MAX_HEIGHT
  43. #define  MED_HEIGHT        109      /* MED_Y+BorderTop+BorderBottom */
  44. #define  BACK                0      /* Background color */
  45. #define  FORE                1      /* Foreground color */
  46. #define  ERRCODE            20      /* Return code in case of trouble */
  47.  
  48. /* ----- The generic OpenLibrary() call ----- */
  49.  
  50. #define  OPENLIB(p,l)  (struct p *)OpenLibrary(l,LIBRARY_VERSION)
  51.  
  52. /* ===== Global variables =============================================== */
  53.  
  54. struct NewWindow NewWindow =        /* Our output window */
  55.    {
  56.    0,0,                             /* Upper left corner */
  57.    HI_WIDTH,HI_HEIGHT,              /* Width and height */
  58.    -1,-1,                           /* Use Wbench's detail and block pens */
  59.    CLOSEWINDOW | NEWSIZE,           /* Ye olde IDCMP */
  60.    WINDOWDEPTH | WINDOWCLOSE        /* Depth, close... */
  61.       | WINDOWDRAG | WINDOWSIZING   /* ...drag, and sizing gadgets */
  62.       | SMART_REFRESH,              /* Let Intuition handle refreshing */
  63.    NULL,                            /* No gadgets */
  64.    NULL,                            /* Or images */
  65.    "",                              /* We'll get the title later */
  66.    NULL,                            /* Use Workbench screen */
  67.    NULL,                            /* No bitmap */
  68.    MIN_WIDTH,MIN_HEIGHT,            /* Smallest size */
  69.    MAX_WIDTH,0,                     /* Largest size */
  70.    WBENCHSCREEN                     /* Standard screen */
  71.    };
  72.  
  73. /* N.B. You can't scale vertically; I couldn't get that to work well */
  74.  
  75. /* ----- These guys are used in main() and Abort() ----- */
  76.  
  77. LONG olddir = NULL;                           /* Lock on former directory */
  78. FILE *Fp = NULL;                              /* File pointer */
  79. struct IntuitionBase *IntuitionBase = NULL;   /* Intuition pointer */
  80. struct GfxBase *GfxBase = NULL;               /* Graphics pointer */
  81. struct Window *Window = NULL;                 /* Pointer to our window */
  82.  
  83. /* ----- These make the program easier to read ----- */
  84.  
  85. #define  ARG     WBenchMsg->sm_ArgList
  86.  
  87. #define  RPORT   Window->RPort         /* Window's RastPort */
  88. #define  UPORT   Window->UserPort      /* Here's the user message port */
  89. #define  LEFT    Window->BorderLeft    /* Offsets into window area */
  90. #define  TOP     Window->BorderTop
  91. #define  RIGHT   (Window->Width - Window->BorderRight - 1)
  92. #define  BOTTOM  (Window->Height - Window->BorderBottom)
  93. #define  WIDTH   (RIGHT - LEFT)
  94. #define  HEIGHT  (BOTTOM - TOP)
  95.  
  96. /* ===== main() ======================================================== */
  97.  
  98. main(argc,argv)
  99. int argc;
  100. char *argv[];
  101. {
  102.    void Abort();                       /* Error handler */
  103.    struct IntuiMessage *GetMsg();      /* Message retrieval */
  104.  
  105.    /* ===== Local variables ============================================= */
  106.  
  107.    extern struct WBStartup *WBenchMsg; /* Startup message from Workbench */
  108.    char *name;                         /* Name of file to open */
  109.    register char Buffer[SEQLEN];       /* Input buffer when scanning */
  110.    register int Max_x = HI_X;          /* Width (for wrap-around) */
  111.    register int Max_y = HI_Y;          /* Height (for bounds checking) */
  112.    long Pos;                           /* File position of picture */
  113.    register int color;                 /* Current color */
  114.    float xFactor,yFactor;              /* Scaling factors for picture */
  115.    float x,y;                          /* Position in picture */
  116.    register char ch;                   /* Single character from file */
  117.    register int New_y,Old_y;           /* Coordinates in window */
  118.  
  119.    register struct IntuiMessage *message;   /* IDCMP message */
  120.    ULONG class;                             /* Message class */
  121.                                                          
  122.    /* ===== Open up file ================================================ */
  123.  
  124.    if (argc == 0)             /* Looks like we were called from Workbench */
  125.       if (WBenchMsg->sm_NumArgs > 1)        /* Did user select a project? */
  126.          if ((++ARG)->wa_Lock) {                  /* Yup, but is lock OK? */
  127.             olddir = CurrentDir(ARG->wa_Lock);    /* Lock current dir */
  128.             name = (ARG--)->wa_Name;              /* Get filename */
  129.             }                       /* (++ and -- select second argument) */
  130.          else
  131.             Abort ("Can't lock directory");
  132.       else
  133.          Abort ("Please select a project");
  134.    else if (argc == 1)                      /* Oops, user forgot filename */
  135.       Abort ("Please specify a filename");
  136.    else                                                 /* Got a filename */
  137.       name = argv[1];
  138.  
  139.    if ((Fp = fopen(name,"r")) == NULL)                /* Try to open file */
  140.       Abort ("Can't open file");
  141.  
  142.    /* ===== Search for picture ========================================== */
  143.  
  144.    strncpy (Buffer,"   ",SEQLEN);
  145.    while (strncmp(Buffer,MED_RES,SEQLEN) && strncmp(Buffer,HI_RES,SEQLEN)
  146.           && NOT feof(Fp)) {
  147.       Buffer[0] = Buffer[1];        /* Buffer holds last three characters */
  148.       Buffer[1] = Buffer[2];                      /* Shift buffer down... */
  149.       Buffer[2] = getc(Fp);        /* ...so we can grab another character */
  150.       }
  151.  
  152.    if (feof(Fp))                               /* File is worthless */
  153.       Abort ("Can't find start of picture");
  154.  
  155.    Pos = ftell(Fp);                            /* Save position */
  156.  
  157.    /* ===== Open up libraries =========================================== */
  158.  
  159.    if ((IntuitionBase = OPENLIB(IntuitionBase,"intuition.library")) == NULL)
  160.       Abort ("Can't open Intuition Library");
  161.  
  162.    if ((GfxBase = OPENLIB(GfxBase,"graphics.library")) == NULL)
  163.       Abort ("Can't open Graphics Library");
  164.  
  165.    /* ===== Open up window ============================================== */
  166.  
  167.    if (NOT strncmp(Buffer,MED_RES,SEQLEN)) {        /* Medium resolution? */
  168.       NewWindow.Width = MED_WIDTH;           /* If so, adjust window size */
  169.       NewWindow.Height = MED_HEIGHT;
  170.       Max_x = MED_X;                               /* ...and picture size */
  171.       Max_y = MED_Y;
  172.       }
  173.  
  174.    NewWindow.Title = argv[1];             /* Set window title to filename */
  175.  
  176.    /* Now it's time to try opening the window */
  177.    if ((Window = (struct Window *)OpenWindow(&NewWindow)) == NULL)
  178.       Abort ("Can't open window");
  179.  
  180.    /* ===== Get ready to show picture =================================== */
  181.  
  182.    do {                          /* We may have to redraw this */
  183.  
  184.       if (fseek(Fp,Pos,0))       /* Go to start of picture */
  185.          Abort ("Fseek woes");
  186.  
  187.       xFactor = (float)WIDTH / Max_x;      /* Scale to fit  */
  188.       yFactor = (float)HEIGHT / Max_y;     /* window snugly */
  189.  
  190.       color = FORE;        /* This flips to BACK initially */
  191.       x = (float)LEFT;
  192.       y = (float)TOP;
  193.       New_y = TOP;
  194.  
  195.       SetAPen (RPORT,BACK);                       /* Clear window */
  196.       RectFill (RPORT,LEFT,TOP,RIGHT,BOTTOM);
  197.  
  198.       Move (RPORT,LEFT,TOP);                /* Start in upper left corner */
  199.  
  200.       /* ===== Go for it ================================================ */
  201.  
  202.       while (NOT feof(Fp) && (message = GetMsg(UPORT)) == NULL) {
  203.  
  204.          SetAPen (RPORT,(color = (color == FORE) ? BACK : FORE));
  205.  
  206.          /* This do-while loop gathers all the consecutive segments
  207.           * for the current color.
  208.           */
  209.  
  210.          do {
  211.  
  212.             /* Specs say we've got to watch out for cursor movement */
  213.  
  214.             while ((ch = getc(Fp)) == ESC)   /* Cursor movement? */
  215.                switch (getc(Fp)) {           /* Yup... */
  216.                   case 'D' :                 /* Left */
  217.                      x -= xFactor;
  218.                      if (x >= LEFT) break;
  219.                      x += WIDTH;
  220.                   case 'A' :                 /* Up */
  221.                      y -= yFactor;
  222.                      if (y < TOP) y += HEIGHT;
  223.                      break;
  224.                   case 'C' :                 /* Right */
  225.                      x += xFactor;
  226.                      if (x <= RIGHT) break;
  227.                      x -= WIDTH;
  228.                   case 'B' :                 /* Down */
  229.                      y += yFactor;
  230.                      if (y > BOTTOM) y -= HEIGHT;
  231.                      break;
  232.                   case 'H' :                 /* Home */
  233.                      x = (float)LEFT;
  234.                      y = (float)TOP;
  235.                      break;
  236.                   case 'Y' :                 /* <lin><col> positioning */
  237.  
  238.                      /* Control characters are invalid */
  239.                      if ((ch = getc(Fp)) < ZERO) ch = ZERO;
  240.  
  241.                      /* Assume line 1 corresponds to y=0 */
  242.                      y = (float)(TOP + ch - ZERO);
  243.  
  244.                      if ((ch = getc(Fp)) < ZERO) ch = ZERO;
  245.                      x = (float)(LEFT + getc(Fp) - ZERO);
  246.                      break;
  247.                   }
  248.  
  249.             if (ch < ZERO) {
  250.                ch = NULL;     /* We don't recognize this character... */
  251.                break;         /* ...so give it up */
  252.                }
  253.  
  254.             /* Not an escape sequence, so assume it's a run-length code */
  255.  
  256.             else if ((x += (ch - ZERO)*xFactor) > RIGHT) {
  257.                y += yFactor;
  258.                x -= WIDTH;
  259.                }
  260.  
  261.             } while ((ch = getc(Fp)) == ZERO);
  262.  
  263.          if (ch == NULL)         /* Don't understand this one... */
  264.             break;               /* ...so we're done */
  265.          else {
  266.             ungetc (ch,Fp);      /* Last character belongs to next color */
  267.             Old_y = New_y;       /* Previous position in window */
  268.             New_y = Round(y);    /* New position */
  269.             }
  270.  
  271.          /* Don't bother drawing if we're going to be overwritten */
  272.  
  273.          if (New_y == Round(y + yFactor))  
  274.             Move (RPORT,Round(x),New_y);   /* Move pen along */
  275.  
  276.          else {
  277.  
  278.             if (New_y > Old_y) {           /* More than one line to draw? */
  279.  
  280.                Draw (RPORT,RIGHT,Old_y);  /* Yep, so finish out this line */
  281.        
  282.                if (New_y > BOTTOM) {   /* ...finish screen if appropriate */
  283.                   RectFill (RPORT,LEFT,Old_y + 1,RIGHT,BOTTOM);
  284.                   break;
  285.                   }
  286.  
  287.                if (New_y - Old_y > 1)        /* ...fill intermediate area */
  288.                   RectFill (RPORT,LEFT,Old_y + 1,RIGHT,New_y - 1);
  289.  
  290.                Move (RPORT,LEFT,New_y);    /* ...and move to the new line */
  291.  
  292.                }
  293.  
  294.             Draw (RPORT,Round(x),New_y);     /* Draw line to new position */
  295.  
  296.             }
  297.  
  298.          if (Chk_Abort()) Abort ("");         /* Abort if user so chooses */
  299.  
  300.          }   /* while */
  301.  
  302.       /* When you size the window and then leave the mouse perfectly still,
  303.        * Wait() and GetMsg() return with message == NULL.  So I put the
  304.        * two statements into a while loop.
  305.        */
  306.  
  307.       while (message == NULL) {          /* Do we have a message? */
  308.          Wait (1 << UPORT->mp_SigBit);   /* No, so sleep 'til we get one */
  309.          message = GetMsg(UPORT);
  310.          }
  311.  
  312.       class = message->Class;    /* What sort of message? */
  313.       ReplyMsg (message);        /* Reply */
  314.  
  315.       } while (class != CLOSEWINDOW);    /* Continue until done */
  316.    
  317.    Abort ("");                           /* We're outta here */
  318.  
  319. }
  320.  
  321.  
  322. /* ===== Round() ========================================================
  323.  *
  324.  * Round() rounds a positive float to the nearest whole number.  Could be
  325.  * a macro, but that would involve four calculations of the expression.
  326.  *
  327.  */
  328.  
  329. int Round(x)
  330. float x;
  331. {
  332.    return ( ((x) - (int)(x) < 0.5)  ?  (int)(x)  :  (int)(x) + 1 );
  333. }
  334.  
  335.  
  336. /* ===== Abort() ========================================================
  337.  *
  338.  * Abort() closes resources and returns the appropriate error code.
  339.  *
  340.  */
  341.  
  342. void Abort (Msg)
  343. char *Msg;         /* Error message */
  344. {
  345.    if (olddir) CurrentDir (olddir);
  346.    if (Fp) fclose (Fp);
  347.    if (IntuitionBase) CloseLibrary (IntuitionBase);
  348.    if (GfxBase) CloseLibrary (GfxBase);
  349.    if (Window) CloseWindow (Window);
  350.    if (stclen(Msg)) {
  351.       fprintf (stderr,"%s.\n",Msg);
  352.       exit (ERRCODE);
  353.       }
  354.    else exit (0);
  355. }
  356.  
  357.